<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>RExpressions - Recursive ASTs!</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Spirit X3 3.0.9">
<link rel="up" href="../tutorials.html" title="Tutorials">
<link rel="prev" href="annotation.html" title="Annotations - Decorating the ASTs">
<link rel="next" href="error_handling.html" title="Error Handling">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="annotation.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorials.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="error_handling.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="spirit_x3.tutorials.rexpr"></a><a class="link" href="rexpr.html" title="RExpressions - Recursive ASTs!">RExpressions - Recursive ASTs!</a>
</h3></div></div></div>
<p>
        In this example, we'll explore more on how to create heierarchical ASTs.
        We will parse a minimalistic JSON-like language and compile the results into
        our data structures in the form of a tree.
      </p>
<p>
        <span class="emphasis"><em>rexpr</em></span> is a parser for RExpressions, a language resembling
        a minimal subset of json, limited to a dictionary (composed of key=value
        pairs) where the value can itself be a string or a recursive dictionary.
      </p>
<p>
        Here's an Example:
      </p>
<pre class="programlisting"><span class="special">{</span>
    <span class="string">"color"</span> <span class="special">=</span> <span class="string">"blue"</span>
    <span class="string">"size"</span> <span class="special">=</span> <span class="string">"29 cm."</span>
    <span class="string">"position"</span> <span class="special">=</span> <span class="special">{</span>
        <span class="string">"x"</span> <span class="special">=</span> <span class="string">"123"</span>
        <span class="string">"y"</span> <span class="special">=</span> <span class="string">"456"</span>
    <span class="special">}</span>
<span class="special">}</span>
</pre>
<p>
        This simple parser for X3 is intended as a minimal starting point. It is
        minimal, yet complete with all things necessary parts that make up rules
        (and grammars), except error handling and reporting.
      </p>
<p>
        The example can be found here: <a href="../../../../../example/x3/rexpr/rexpr_min/rexpr.cpp" target="_top">rexpr.cpp</a>
      </p>
<p>
        The same parser, but complete with error handling and reporting, better file
        organization, separate compilation of grammars, and a full test harness,
        can be found in this directory:
      </p>
<p>
        <a href="../../../../../example/x3/rexpr/rexpr_full/" target="_top">rexpr/rexpr_full/</a>
      </p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
          rexpr_full is the canonical structure proposed as best practice on how
          parsers are written using Spirit X3.
        </p></td></tr>
</table></div>
<h5>
<a name="spirit_x3.tutorials.rexpr.h0"></a>
        <span class="phrase"><a name="spirit_x3.tutorials.rexpr.the_ast"></a></span><a class="link" href="rexpr.html#spirit_x3.tutorials.rexpr.the_ast">The
        AST</a>
      </h5>
<p>
        Here's the AST:
      </p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">client</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">ast</span>
<span class="special">{</span>
    <span class="keyword">namespace</span> <span class="identifier">x3</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">x3</span><span class="special">;</span>

    <span class="keyword">struct</span> <span class="identifier">rexpr</span><span class="special">;</span>

    <span class="keyword">struct</span> <span class="identifier">rexpr_value</span> <span class="special">:</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">variant</span><span class="special">&lt;</span>
            <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span>
          <span class="special">,</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">forward_ast</span><span class="special">&lt;</span><span class="identifier">rexpr</span><span class="special">&gt;</span>
        <span class="special">&gt;</span>
    <span class="special">{</span>
        <span class="keyword">using</span> <span class="identifier">base_type</span><span class="special">::</span><span class="identifier">base_type</span><span class="special">;</span>
        <span class="keyword">using</span> <span class="identifier">base_type</span><span class="special">::</span><span class="keyword">operator</span><span class="special">=;</span>
    <span class="special">};</span>

    <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="identifier">rexpr_value</span><span class="special">&gt;</span> <span class="identifier">rexpr_map</span><span class="special">;</span>
    <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="identifier">rexpr_value</span><span class="special">&gt;</span> <span class="identifier">rexpr_key_value</span><span class="special">;</span>

    <span class="keyword">struct</span> <span class="identifier">rexpr</span>
    <span class="special">{</span>
        <span class="identifier">rexpr_map</span> <span class="identifier">entries</span><span class="special">;</span>
    <span class="special">};</span>
<span class="special">}}</span>
</pre>
<p>
        <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">variant</span></code> is a support utility in Spirit
        X3 that extends <a href="http://www.boost.org/doc/html/variant.html" target="_top">Boost.Variant</a>.
        Typically, you use <a href="http://www.boost.org/doc/html/variant.html" target="_top">Boost.Variant</a>
        right out of the box and refer to a particular template instantiation using
        a typedef. For example:
      </p>
<pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">my_variant</span><span class="special">;</span>
</pre>
<p>
        Instead of doing that, we create a <code class="computeroutput"><span class="keyword">class</span></code>
        (or <code class="computeroutput"><span class="keyword">struct</span></code> in the case) that
        subclasses from <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">variant</span></code>. By making the variant a subclass,
        you have a distinct type in your namespace. You also have control of the
        constructors and assignment operators, as well as giving you the freedom
        to add more functionality.
      </p>
<p>
        <code class="computeroutput"><span class="identifier">rexpr_value</span></code> has two variant
        elements. It can either be a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
        or a <code class="computeroutput"><span class="identifier">rexpr</span></code>. Since <code class="computeroutput"><span class="identifier">rexpr</span></code> recursively contains a <code class="computeroutput"><span class="identifier">rexpr_value</span></code>, it has to be forward declared.
        This recursive data structure requires <code class="computeroutput"><span class="identifier">rexpr</span></code>
        to be wrapped in a <code class="computeroutput"><span class="identifier">x3</span><span class="special">::</span><span class="identifier">forward_ast</span></code> as shown in the declaration.
      </p>
<p>
        We need to tell fusion about our <code class="computeroutput"><span class="identifier">rexpr</span></code>
        struct to make it a first-class fusion citizen:
      </p>
<pre class="programlisting"><span class="identifier">BOOST_FUSION_ADAPT_STRUCT</span><span class="special">(</span>
    <span class="identifier">client</span><span class="special">::</span><span class="identifier">ast</span><span class="special">::</span><span class="identifier">rexpr</span><span class="special">,</span>
    <span class="identifier">entries</span>
<span class="special">)</span>
</pre>
<p>
        So essentially, a <code class="computeroutput"><span class="identifier">rexpr_value</span></code>
        value is either a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> or a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="identifier">rexpr_value</span><span class="special">&gt;</span></code>.
      </p>
<h5>
<a name="spirit_x3.tutorials.rexpr.h1"></a>
        <span class="phrase"><a name="spirit_x3.tutorials.rexpr.walking_the_ast"></a></span><a class="link" href="rexpr.html#spirit_x3.tutorials.rexpr.walking_the_ast">Walking
        the AST</a>
      </h5>
<p>
        We add a utility to print out the AST:
      </p>
<pre class="programlisting"><span class="keyword">int</span> <span class="keyword">const</span> <span class="identifier">tabsize</span> <span class="special">=</span> <span class="number">4</span><span class="special">;</span>

<span class="keyword">struct</span> <span class="identifier">rexpr_printer</span>
<span class="special">{</span>
    <span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">result_type</span><span class="special">;</span>

    <span class="identifier">rexpr_printer</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">indent</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span>
      <span class="special">:</span> <span class="identifier">indent</span><span class="special">(</span><span class="identifier">indent</span><span class="special">)</span> <span class="special">{}</span>

    <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">rexpr</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">ast</span><span class="special">)</span> <span class="keyword">const</span>
    <span class="special">{</span>
        <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="char">'{'</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
        <span class="keyword">for</span> <span class="special">(</span><span class="keyword">auto</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">entry</span> <span class="special">:</span> <span class="identifier">ast</span><span class="special">.</span><span class="identifier">entries</span><span class="special">)</span>
        <span class="special">{</span>
            <span class="identifier">tab</span><span class="special">(</span><span class="identifier">indent</span><span class="special">+</span><span class="identifier">tabsize</span><span class="special">);</span>
            <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="char">'"'</span> <span class="special">&lt;&lt;</span> <span class="identifier">entry</span><span class="special">.</span><span class="identifier">first</span> <span class="special">&lt;&lt;</span> <span class="string">"\" = "</span><span class="special">;</span>
            <span class="identifier">boost</span><span class="special">::</span><span class="identifier">apply_visitor</span><span class="special">(</span><span class="identifier">rexpr_printer</span><span class="special">(</span><span class="identifier">indent</span><span class="special">+</span><span class="identifier">tabsize</span><span class="special">),</span> <span class="identifier">entry</span><span class="special">.</span><span class="identifier">second</span><span class="special">);</span>
        <span class="special">}</span>
        <span class="identifier">tab</span><span class="special">(</span><span class="identifier">indent</span><span class="special">);</span>
        <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="char">'}'</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
    <span class="special">}</span>

    <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">text</span><span class="special">)</span> <span class="keyword">const</span>
    <span class="special">{</span>
        <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="char">'"'</span> <span class="special">&lt;&lt;</span> <span class="identifier">text</span> <span class="special">&lt;&lt;</span> <span class="char">'"'</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
    <span class="special">}</span>

    <span class="keyword">void</span> <span class="identifier">tab</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">spaces</span><span class="special">)</span> <span class="keyword">const</span>
    <span class="special">{</span>
        <span class="keyword">for</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">spaces</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span>
            <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="char">' '</span><span class="special">;</span>
    <span class="special">}</span>

    <span class="keyword">int</span> <span class="identifier">indent</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
        Traversing the AST is a recursive exercise. <code class="computeroutput"><span class="identifier">rexpr_printer</span></code>
        is a function object and the main entry point is <code class="computeroutput"><span class="keyword">void</span>
        <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">rexpr</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">ast</span><span class="special">)</span></code>. Notice how it recursively calls an instance
        of itself for each of the key value pairs, using <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">apply_visitor</span></code>.
        Before and after iterating through all the elements in the map, the braces
        are printed to surround the entire body, taking care of correct indentation
        at each point in the recursive traversal.
      </p>
<p>
        The <code class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></code>
        for <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> should be self explanatory. It simply
        prints the text inside double quotes.
      </p>
<h5>
<a name="spirit_x3.tutorials.rexpr.h2"></a>
        <span class="phrase"><a name="spirit_x3.tutorials.rexpr.the_grammar"></a></span><a class="link" href="rexpr.html#spirit_x3.tutorials.rexpr.the_grammar">The
        Grammar</a>
      </h5>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">client</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">parser</span>
<span class="special">{</span>
    <span class="keyword">namespace</span> <span class="identifier">x3</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">x3</span><span class="special">;</span>
    <span class="keyword">namespace</span> <span class="identifier">ascii</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">spirit</span><span class="special">::</span><span class="identifier">x3</span><span class="special">::</span><span class="identifier">ascii</span><span class="special">;</span>

    <span class="keyword">using</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">lit</span><span class="special">;</span>
    <span class="keyword">using</span> <span class="identifier">x3</span><span class="special">::</span><span class="identifier">lexeme</span><span class="special">;</span>

    <span class="keyword">using</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">char_</span><span class="special">;</span>
    <span class="keyword">using</span> <span class="identifier">ascii</span><span class="special">::</span><span class="identifier">string</span><span class="special">;</span>

    <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">rexpr_value</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">::</span><span class="identifier">rexpr_value</span><span class="special">&gt;</span>
        <span class="identifier">rexpr_value</span> <span class="special">=</span> <span class="string">"rexpr_value"</span><span class="special">;</span>

    <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">rexpr</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">::</span><span class="identifier">rexpr</span><span class="special">&gt;</span>
        <span class="identifier">rexpr</span> <span class="special">=</span> <span class="string">"rexpr"</span><span class="special">;</span>

    <span class="identifier">x3</span><span class="special">::</span><span class="identifier">rule</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">rexpr_key_value</span><span class="special">,</span> <span class="identifier">ast</span><span class="special">::</span><span class="identifier">rexpr_key_value</span><span class="special">&gt;</span>
        <span class="identifier">rexpr_key_value</span> <span class="special">=</span> <span class="string">"rexpr_key_value"</span><span class="special">;</span>

    <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">quoted_string</span> <span class="special">=</span>
        <span class="identifier">lexeme</span><span class="special">[</span><span class="char">'"'</span> <span class="special">&gt;&gt;</span> <span class="special">*(</span><span class="identifier">char_</span> <span class="special">-</span> <span class="char">'"'</span><span class="special">)</span> <span class="special">&gt;&gt;</span> <span class="char">'"'</span><span class="special">];</span>

    <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">rexpr_value_def</span> <span class="special">=</span>
        <span class="identifier">quoted_string</span> <span class="special">|</span> <span class="identifier">rexpr</span><span class="special">;</span>

    <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">rexpr_key_value_def</span> <span class="special">=</span>
        <span class="identifier">quoted_string</span> <span class="special">&gt;&gt;</span> <span class="char">'='</span> <span class="special">&gt;&gt;</span> <span class="identifier">rexpr_value</span><span class="special">;</span>

    <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">rexpr_def</span> <span class="special">=</span>
        <span class="char">'{'</span> <span class="special">&gt;&gt;</span> <span class="special">*</span><span class="identifier">rexpr_key_value</span> <span class="special">&gt;&gt;</span> <span class="char">'}'</span><span class="special">;</span>

    <span class="identifier">BOOST_SPIRIT_DEFINE</span><span class="special">(</span><span class="identifier">rexpr_value</span><span class="special">,</span> <span class="identifier">rexpr</span><span class="special">,</span> <span class="identifier">rexpr_key_value</span><span class="special">);</span>
<span class="special">}}</span>
</pre>
<p>
        We declare three rules <code class="computeroutput"><span class="identifier">rexpr_value</span></code>,
        <code class="computeroutput"><span class="identifier">rexpr</span></code> and <code class="computeroutput"><span class="identifier">rexpr_key_value</span></code>.
        Same deal as before. The attributes declared for each rule are the same structures
        we declared in our AST above. These are the structures our rules will produce.
      </p>
<p>
        So, going top-down (from the start rule), <code class="computeroutput"><span class="identifier">rexpr</span></code>
        is defined as zero or more <code class="computeroutput"><span class="identifier">rexpr_key_value</span></code>s
        enclosed inside the curly braces. That's the kleene star in action there:
        <code class="computeroutput"><span class="special">*</span><span class="identifier">rexpr_key_value</span></code>.
      </p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
          Take note of the convention: we use <code class="computeroutput"><span class="identifier">rexpr</span></code>
          name as the rule name and <code class="computeroutput"><span class="identifier">rexpr_def</span></code>
          as the rule definition name.
        </p></td></tr>
</table></div>
<p>
        To make the grammar clean, we capture the <code class="computeroutput"><span class="identifier">quoted_string</span></code>
        production using C++ <code class="computeroutput"><span class="keyword">auto</span></code>.
      </p>
<p>
        <code class="computeroutput"><span class="identifier">rexpr_value</span></code> is a <code class="computeroutput"><span class="identifier">quoted_string</span></code> followed by the assignment
        operator <code class="computeroutput"><span class="char">'='</span></code>, followed by a <code class="computeroutput"><span class="identifier">rexpr_value</span></code>. <code class="computeroutput"><span class="identifier">rexpr_value</span></code>
        is a <code class="computeroutput"><span class="identifier">quoted_string</span></code> <span class="emphasis"><em>OR</em></span>
        a <code class="computeroutput"><span class="identifier">rexpr</span></code>. This uses the alternative
        operator <code class="computeroutput"><span class="special">|</span></code>, and maps nicely
        to the variant AST the rule is associated with.
      </p>
<p>
        Finally, we associate the rules and their definitions:
      </p>
<pre class="programlisting"><span class="identifier">BOOST_SPIRIT_DEFINE</span><span class="special">(</span><span class="identifier">rexpr_value</span><span class="special">,</span> <span class="identifier">rexpr</span><span class="special">,</span> <span class="identifier">rexpr_key_value</span><span class="special">);</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2001-2018 Joel de Guzman,
      Hartmut Kaiser<p>
        Distributed under the Boost Software License, Version 1.0. (See accompanying
        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
      </p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="annotation.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorials.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="error_handling.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
